<template>
  <u-popup
    ref="popupRef"
    v-model="props.modelValue"
    :maskCloseAble="maskCloseAble"
    mode="bottom"
    :popup="false"
    length="auto"
    :safeAreaInsetBottom="safeAreaInsetBottom"
    @close="close">
    <!-- 标题栏区域 -->
    <div
      class="u-picker-header w-full h-90rpx px-30rpx relative flex justify-between items-center box-border text-30rpx text-white"
      @touchmove.stop.prevent="">
      <div
        class="u-btn-picker u-btn-picker--tips p-16rpx box-border text-center text-hex-606266 no-underline"
        :hover-stay-time="150"
        @click="handleCancel">
        取消
      </div>
      <div class="u-picker__title text-hex-606266">{{ title }}</div>
      <div
        class="u-btn-picker u-btn-picker--primary"
        :class="isMoving ? 'text-hex-606266' : 'text-primary'"
        :hover-stay-time="150"
        @touchmove.stop=""
        @click="handleConfirm">
        确认
      </div>
    </div>
    <!-- 热门城市 -->
    <div
      class="popular-city w-full"
      v-if="showPopularCity">
      <div class="title w-full pl-30rpx text-26rpx text-primary">热门城市</div>
      <div class="popular-city-container flex flex-wrap mb-20rpx px-30rpx text-center">
        <div
          class="popular-city-item w-22vw h-70rpx text-center text-28rpx text-hex-666666 bg-hex-f6f6f6"
          :class="popularCitySelected === index ? 'popular-city-selected' : ''"
          v-for="(city, index) in popularCity"
          :key="index"
          @click="selectPopularCity(index)">
          {{ city.name }}
        </div>
      </div>
      <div class="title w-full pl-30rpx mb-20rpx text-26rpx text-primary">选择地区</div>
    </div>
    <!-- 地区选择器 -->
    <div class="u-datetime-picker relative">
      <div
        class="u-picker-body w-full bg-white overflow-hidden"
        :style="{height: `${showPopularCity ? '400rpx' : '500rpx'}`}">
        <picker-view
          class="u-picker-view h-full box-border"
          :value="valueArr"
          @pickstart="pickStart"
          @change="pickChange"
          @pickend="pickEnd">
          <picker-view-column v-if="!reset">
            <div
              class="u-column-item flex items-center justify-center text-30rpx px-8rpx"
              v-for="(item, index) in provinces"
              :key="index">
              <div class="u-line-1">{{ item.name }}</div>
            </div>
          </picker-view-column>
          <picker-view-column v-if="!reset">
            <div
              class="u-column-item flex items-center justify-center text-30rpx px-8rpx"
              v-for="(item, index) in cities"
              :key="index">
              <div class="u-line-1">{{ item.name }}</div>
            </div>
          </picker-view-column>
          <picker-view-column v-if="!reset">
            <div
              class="u-column-item flex items-center justify-center text-30rpx px-8rpx"
              v-for="(item, index) in areas"
              :key="index">
              <div class="u-line-1">{{ item.name }}</div>
            </div>
          </picker-view-column>
        </picker-view>
      </div>
    </div>
  </u-popup>
</template>

<script setup lang="ts">
  import {AddressData, popularCityList, SelectResult} from '@/components/select-popup/select-area'

  import provinceData from 'vk-uview-ui/libs/address/provinces.json'
  import cityData from 'vk-uview-ui/libs/address/citys.json'
  import areaData from 'vk-uview-ui/libs/address/areas.json'

  interface SelectAreaProps {
    modelValue: boolean
    defaultAreaCode?: Array<string> | any
    safeAreaInsetBottom?: boolean
    maskCloseAble?: boolean
    title?: string
    showPopularCity?: boolean
  }

  const props = withDefaults(defineProps<SelectAreaProps>(), {
    modelValue: false,
    defaultAreaCode: ['44', '4401', '440103'],
    safeAreaInsetBottom: false,
    maskCloseAble: false,
    title: '',
    showPopularCity: true
  })

  const emit = defineEmits<{
    (e: 'update:modelValue', modelValue: boolean): void,
    (e: 'confirm', result: SelectResult): void,
    (e: 'cancel', result: SelectResult): void,
    (e: 'input', value: boolean): void,
  }>()

  const popupRef = ref<any>(null)

  const reset = ref(false)  //是否重置
  const valueArr = ref<Array<any>>([]) //地区数组
  const provinces = ref(provinceData)
  const cities = ref(cityData[0])
  const areas = ref(areaData[0][0])
  const province = ref<number | string>(0)
  const city = ref<number | string>(0)
  const area = ref<number | string>(0)
  const isMoving = ref(false)  // Picker是否在滑动过程中
  const popularCity = popularCityList //热门城市列表
  const popularCitySelected = ref(-1) //热门城市当前选中的序号，值为-1则未选任何热门城市

  /**
   * 根据行政编码查询地区名称
   * @param adCode 行政编码，例："440104"
   * @return {Boolean|Array} 查询失败返回false，查询成功返回名称数组，格式：[省份, 城市, 区县]
   */
  const queryAreaName = (adCode: string): boolean | Array<string> => {
    let result: any[] = []
    let provinceIndex: number = 0
    let cityIndex: number = 0
    try {
      const areaCodeArray = [`${adCode.slice(0, 2)}0000`, `${adCode.slice(0, 4)}00`, adCode]
      provinceData?.map((v: AddressData, k: number) => {
        if (v.code === areaCodeArray[0]) {
          result[0] = v.name
          provinceIndex = k
        }
      })
      cityData[provinceIndex]?.map((v: AddressData, k: number) => {
        if (v.code === areaCodeArray[1]) {
          result[1] = v.name
          cityIndex = k
        }
      })
      areaData[provinceIndex][cityIndex]?.map((v: AddressData, k: number) => {
        if (v.code === areaCodeArray[2]) {
          result[2] = v.name
        }
      })
    } catch (e) {
      console.error(e)
      return false
    }
    return result
  }

  // 初始化
  const init = (): void => {
    valueArr.value = []
    reset.value = false
    valueArr.value.push(0)
    setProvinces()
    valueArr.value.push(0)
    setCities()
    valueArr.value.push(0)
    setAreas()
  }

  defineExpose({init, queryAreaName})

  // 设置省份
  const setProvinces = (): void => {
    let tmp: number | string = ''
    let useCode = false
    if (popularCitySelected.value !== -1) {
      tmp = popularCity[popularCitySelected.value].province
    } else if (props.defaultAreaCode.length) {
      tmp = `${props.defaultAreaCode[0]}0000`
      useCode = true
    } else tmp = 0
    provinceData?.map((v: AddressData, k: number) => {
      if (useCode ? v.code === tmp : v.name === tmp) {
        tmp = k
      }
    })
    province.value = tmp
    provinces.value = provinceData
    // 设置默认省份的值
    valueArr.value.splice(0, 1, province.value)
  }

  // 设置城市
  const setCities = (): void => {
    let tmp: number | string = ''
    let useCode = false
    if (popularCitySelected.value !== -1) {
      tmp = popularCity[popularCitySelected.value].city
    } else if (props.defaultAreaCode.length) {
      tmp = `${props.defaultAreaCode[1]}00`
      useCode = true
    } else tmp = 0
    cityData[province.value as number]?.map((v: AddressData, k: number) => {
      if (useCode ? v.code === tmp : v.name === tmp) {
        tmp = k
      }
    })
    city.value = tmp
    cities.value = cityData[province.value as number]
    valueArr.value.splice(1, 1, city.value)
  }

  // 设置区县
  const setAreas = (): void => {
    let tmp: number | string = ''
    let useCode = false
    if (popularCitySelected.value !== -1) {
      tmp = popularCity[popularCitySelected.value].area
    } else if (props.defaultAreaCode.length) {
      tmp = props.defaultAreaCode[2]
      useCode = true
    } else tmp = 0
    areaData[province.value as number][city.value as number]?.map((v: AddressData, k: number) => {
      if (useCode ? v.code === tmp : v.name === tmp) {
        tmp = k
      }
    })
    area.value = tmp
    areas.value = areaData[province.value as number][city.value as number]
    valueArr.value.splice(2, 1, area.value)
  }

  /**
   * 选择热门城市
   * @param index 选择的热门城市的序号
   */
  const selectPopularCity = (index: number): void => {
    popularCitySelected.value = index
    reset.value = true
    init()
    isMoving.value = false
  }

  // Picker滑动开始
  const pickStart = (): void => {
    isMoving.value = true
  }

  // Picker滑动结束
  const pickEnd = (): void => {
    isMoving.value = false
    if (popularCitySelected.value !== -1) {
      if (popularCity[popularCitySelected.value].province !== provinceData[province.value as number].name
        || popularCity[popularCitySelected.value].city !== cityData[province.value as number][city.value as number].name) {
        popularCitySelected.value = -1
      }
    }
  }

  // 用户更改Picker的列选项
  const pickChange = (e: CustomEvent): void => {
    valueArr.value = e.detail.value
    let i = 0
    province.value = valueArr.value[i++]
    city.value = valueArr.value[i++]
    area.value = valueArr.value[i++]
  }

  // 用户点击确定按钮
  const handleConfirm = (): void => {
    if (isMoving.value) return
    let result: SelectResult = {}
    result.action = 'confirm'
    result.province = provinceData[province.value as number]
    result.city = cityData[province.value as number][city.value as number]
    result.area = areaData[province.value as number][city.value as number][area.value as number]
    emit('confirm', result) //绑定confirm事件，回传已选择地区的结果集
    close()
  }

  // 用户点击取消按钮或者点击遮罩层
  const handleCancel = (): void => {
    if (isMoving.value) return
    let result: SelectResult = {}
    result.action = 'cancel'
    result.province = provinceData[province.value as number]
    result.city = cityData[province.value as number][city.value as number]
    result.area = areaData[province.value as number][city.value as number][area.value as number]
    emit('cancel', result) //绑定cancel事件，回传已选择地区的结果集
    close()
  }

  // 关闭Picker
  const close = (e?: CustomEvent): void => {
    emit('update:modelValue', false)
    emit('input', false)
  }

  //强制触发props变化监听器
  const propsChange = computed(() => `${props.defaultAreaCode}`)
  watch(
    () => propsChange,
    () => {
      reset.value = true
      setTimeout(() => init(), 10)
    }
  )

  //强制触发地区变化监听器
  const regionChange = computed(() => `${province.value}-${city.value}`)
  watch(
    () => regionChange.value,
    () => {
      cities.value = cityData[province.value as number]
      areas.value = areaData[province.value as number][city.value as number]
    }
  )
</script>

<style scoped lang="scss">
  @import 'select-area';
</style>